<?php
/**
* DIXon Generation 1 - JavaScript Client Pages
* 
* PHP Bindings for PHP 5.2.x and above
* 
* Copyright (c) 2008, Artem Ploujnikov
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided  that the following conditions are met:
* 
*  * Redistributions of source code must retain the above copyright notice, this 
*    list of conditions and the following disclaimer.
*  * Redistributions in binary form must reproduce the above copyright notice, this 
* 	 list of conditions and the following disclaimer in the documentation and/or 
*    other materials provided with the distribution.
* *  Neither the name of Artem Ploujnikov nor the names of the project's contributors 
* 	 may be used to endorse or promote products derived from this software without 
*    specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE. 
*/


/**
* A base class for DiXon exception classes
* 
* @author Artem Ploujnikov 
*/
class DiXon_Exception extends Exception {

	/**
	* The DiXon configuration that caused this
	* exception
	* 
	* @var DiXon_Configuration
	*/
	private $configuration;
	
	/**
	* Creates a new DiXon exception
	* 
	* @param string 				$code the exception code
	* @param DiXon_Configuration    the DiXon configuration instance from which
	* 	error messages will be retrieved. If none is provided, the default file 
	* 	will be used.
	*/
	public function DiXon_Exception($code) {
		$this->configuration = DiXon_Configuration::getInstance();

		$arguments =
			array_slice( 
				func_get_args(),
				1
			);
		
		
        parent::__construct(
        	self::formatMessage(
        		$this->configuration->getValue(
        			DiXon_Configuration::ErrorPrefix . $code,
        			DiXon_Configuration::ErrorSection
        		),
        		$arguments
        	),
        	$code
        );
	}
	
	/**
	* Formats a message using the provided template, replacing placeholders
	* formatted as {n} (i.e. {0}, {1}, {2}, {3}, ...) with the nth argument
	* from the provided argument list
	* 
	* @param string $message the message template
	* @param string $arguments the arguments to be substituted for placeholders
	* 
	* @return string
	*/
	public static function formatMessage($message, $arguments) {
		$finalMessage = $message;
		for ($i=0, $length = count($arguments); $i<$length;$i++) {
			$placeholder = '{' . $i . '}';
			$finalMessage = str_replace(
				$placeholder,
				$arguments[$i],
				$finalMessage
			);
		}		
		return $finalMessage;	
	}
	
	/**
	* Returns the DiXon configuration instance corresponding to the
	* configuration that caused this exception
	* 
	* @return DiXon_Configuration
	*/
	public function getConfiguration() {
		return $this->configuration;
	}
}

/**
* Thrown when a file cannot be found
*/
class DiXon_FileNotFoundException extends DiXon_Exception {
	const ErrorCode = 100;
	
	
	/**
	* The name of the file that was not found.
	* 
	* @var string
	*/
	private $fileName;
	
	
	/**
	* Creates a new File Not Found exception
	* 
	* @param string $fileName the name of a required file that was
	* 	not found
	* 
	* @return DiXon_FileNotFoundException
	*/
	public function __construct($fileName) {
		parent::__construct(self::ErrorCode, $fileName);
	}
	
	/**
	* Returns the name of the file that was not found
	* 
	* @return string
	*/
	public function getFileName() {
		return $this->fileName;
	}	
}

/**
* Constants for the different types of files in the
* file system.
*/
class DiXon_FileType {
	const Directory = 'directory';
	const File = 'file';
}

/**
* Thrown when the bootstrapper finds a directory where it
* expects a file or vice versa
*/
class DiXon_WrongFileTypeException extends DiXon_Exception {
	const ErrorCode = 101;
	
	/**
	* The name of the file that caused the exception
	* 
	* @var string
	*/
	private $fileName;
	
	/**
	* The expected file type
	* 
	* @var string
	*/
	private $expectedType;
	
	/**
	* The actual file type
	* 
	* @var string
	*/
	private $actualType;
	
	/**
	* Creates a new Wrong File Type exception
	* 
	* @param string $fileName 	  the full path to the file in question
	* @param string $actualType   the actual file type
	* @param string $expectedType the expected file type
	* 
	* @return DiXon_WrongFileTypeException
	*/
	public function __construct($fileName, $actualType, $expectedType) {
		parent::__construct(self::ErrorCode, $fileName, $actualType, $expectedType);
		$this->fileName = $fileName;
		$this->expectedType = $expectedType;
		$this->actualType = $actualType;
	}
	
	/**
	* Returns the path to the file that caused
	* the exception
	* 
	* @return string
	*/
	public function getFileName() {
		return $this->fileName;
	}
	
	/**
	* Returns the expected type according to the program
	* logic
	* 
	* @return string
	*/
	public function getExpectedType() {
		return $this->expectedType;
	}
	
	/**
	* Returns the actual file type
	* 
	* @return string
	*/
	public function getActualType() {
		return $this->actualType;
	}
}

/**
* Thrown when a file or a directory cannot be created
*/
class DiXon_CreateFileException extends DiXon_Exception {
	/**
	* CreateFileException = 102
	*/
	const ErrorCode = 102;
	
	/**
	* The name of the file the application was trying to create
	* 
	* @var string
	*/
	private $fileName;
	
	/**
	* The type of the file that should have been created
	* 
	* @var string
	*/
	private $type;
	
	
	/**
	* Creates a new Create File exception
	* 
	* @param string $fileName the name of the file the application was
	* 	trying to create
	* @param string $type the type of the file that should have been
	* 	created
	*/
	public function __construct($fileName, $type) {
		parent::__construct(
			self::ErrorCode,
			$fileName,
			$type
		);
		
		$this->fileName = $fileName;
		$this->type = $type;
	}
	
	/**
	* Returns the name of the file the application was trying to
	* create
	* 
	* @return string
	*/
	public function getFileName() {
		return $this->fileName;
	}
	
	/**
	* Returns the type of the file that should have been created.
	* 
	* @return string
	*/
	public function getType() {
		return $this->type;
	}
	
}

/**
* Constants for permissions
*/
class DiXon_Permission {
	const Read = 'read';
	const Write = 'write';
}

/**
* Thrown when the underlying operating environment makes it impossible
* to access a required file
*/
class DiXon_FilePermissionDeniedException extends DiXon_Exception {
	const ErrorCode = 103;
	
	/**
	* The name of the file the application tried to access
	* 
	* @var string
	*/
	private $fileName;
	
	/**
	* The missing permission
	* 
	* @return string
	*/
	private $requiredPermission;
	
	/**
	* Creates a new File Permission Denied exception
	* 
	* @param string $fileName the name of the file for which the permission
	* 	in question was requested
	* 
	* @param string $requiredPermission the permission that was necessary for
	* 	the operation to complete and yet denied by the operating environment
	* 
	* @return DiXon_FilePermissionDeniedException
	*/
	public function __construct($fileName, $requiredPermission) {
		parent::__construct(
			self::ErrorCode,
			$fileName,
			$requiredPermission
		);
		$this->fileName = $fileName;
		$this->requiredPermission = $requiredPermission;
	}
	
	
	/**
	* Returns the name of the file for which the permission in question
	* was requested
	* 
	* @return string
	*/
	public function getFileName() {
		return $this->fileName;
	}
	
	/**
	* Returns the permission that was required for the operation to
	* complete and yet denied by the operating environment.
	* 
	* @return string
	*/
	public function getRequiredPermission() {
		return $this->requiredPermission;
	}
	
}

?>